package com.zhixi.controller;

import com.zhixi.utils.UploadUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @ClassName FileController
 * @Author zhangzhixi
 * @Description
 * @Date 2022-4-18 12:30
 * @Version 1.0
 */
@Controller
public class FileUpLoadController {

    Logger log = LoggerFactory.getLogger(FileUpLoadController.class);


    @Value("${local.upload.path}")
    String localUploadPath;

    /**
     * 返回项目首页
     *
     * @return 首页
     */
    @GetMapping("/")
    public String index() {
        return "index";
    }

    /**
     * 返回上传页面
     *
     * @return 上传页面
     */
    @GetMapping("/toUpload")
    public String upload(Model model) throws IOException {
        /*文件列表*/
        List<String> filesName = getFile(model);
        model.addAttribute("filesName", filesName);
        return "upload";
    }

    // 获取文件夹下的文件
    public List<String> getFile(Model model) throws IOException {
        //获取项目相对路径,上传文件到项目资源目录的upload下
        File directory = new File(localUploadPath);

        File realFile = new File(directory.getCanonicalPath());
        if (!realFile.exists()) {
            realFile.mkdirs();
        }

        List<String> list = new ArrayList<>();
        // 获取文件夹下的所有文件
        File[] files = realFile.listFiles();
        for (File file : files) {
            // 判断是否是文件夹
            if (file.isDirectory()) {
                System.out.println("文件夹名称：" + file.getName());
            }
            // 判断是否是文件
            if (file.isFile()) {
                list.add(file.getName());
            }
        }
        return list;
    }

    /**
     * 单文件上传
     *
     * @param request  请求
     * @param response 响应
     * @return 上传页面
     */
    @RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
    public String upload(HttpServletRequest request, HttpServletResponse response, @RequestParam("file") MultipartFile file, Model model) throws IOException {
        /*设置编码*/
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        // 测试MultipartFile接口的各个方法
        System.out.println("文件类型ContentType:" + file.getContentType());
        System.out.println("文件组件名称Name:" + file.getName());
        System.out.println("文件原名称OriginalFileName:" + file.getOriginalFilename());
        System.out.println("文件大小Size:" + file.getSize() / 1024 + "KB");
        try {
            if (file.isEmpty()) {
                model.addAttribute("msg", "<font color=\"red\">上传失败，文件为空</font>");
                return "upload";
            }
            // 获取文件名
            String fileName = file.getOriginalFilename();
            // 获取文件名称的前缀
            assert fileName != null;
            String prefix = fileName.substring(0, fileName.lastIndexOf("."));
            // 获取文件的后缀名
            String suffixName = fileName.substring(fileName.lastIndexOf("."));
            log.info("文件的后缀名为：" + suffixName);


            //获取文件相对路径
            File directory = new File(localUploadPath);
            String realPath = directory.getCanonicalPath();
            System.out.println("上传的文件夹是：" + realPath);

            //构造一个路径
            String newFile = prefix + UUID.randomUUID() + suffixName;
            String path = realPath + File.separatorChar + newFile;
            log.info("构造路径" + path);

            File dest = new File(path);
            // 检测是否存在目录
            if (!dest.getParentFile().exists()) {
                // 新建文件夹
                dest.getParentFile().mkdirs();
            }
            // 文件写入
            file.transferTo(dest);
            model.addAttribute("msg", "<font color=\"green\">上传成功</font>");
            /*用于文件的下载*/
            model.addAttribute("img", newFile);
            /*文件列表*/
            List<String> filesName = getFile(model);
            model.addAttribute("filesName", filesName);

            return "upload";
        } catch (IllegalStateException | IOException e) {
            e.printStackTrace();
        }

        /*文件列表*/
        List<String> filesName = getFile(model);
        model.addAttribute("filesName", filesName);
        model.addAttribute("msg", "<font color=\"red\">上传失败</font>");
        return "upload";
    }


    /**
     * 文件上传请求：多文件+单文件
     */
    @PostMapping("/uploadMultiple")
    public String toUpLoad(@RequestParam("email") String email,
                           @RequestParam("username") String username,
                           // 单文件上传
                           @RequestPart("headImg") MultipartFile headImg,
                           // 多文件上传
                           @RequestPart("photos") MultipartFile[] photos,
                           Model model) throws IOException {
        System.out.println("email：" + email);
        System.out.println("用户名：" + username);
        System.out.println("单文件的文件大小：" + headImg.getSize() / 1024 + "KB");
        System.out.println("多文件的文件个数：" + photos.length);

        //获取项目相对路径,上传文件到项目资源目录的upload下
        File directory = new File(localUploadPath);
        String realPath = directory.getCanonicalPath();
        System.out.println("上传的文件夹是：" + realPath);

        File file = new File(realPath);
        if (!file.exists()) {
            file.mkdirs();
        }

        boolean singleFlag = false;
        boolean multiFlag = false;

        // 保存单文件的上传地址
        if (!headImg.isEmpty()) {
            // 获取文件名
            String filename = headImg.getOriginalFilename();
            /*将文件写入到文件夹中*/
            headImg.transferTo(new File(file.getAbsolutePath() + File.separator + System.currentTimeMillis() + filename));
            singleFlag = true;
        }
        // 保存多文件的上传地址,不选文件上传时，photos为1个空文件
        if (photos.length > 1) {
            for (MultipartFile photo : photos) {
                if (!photo.isEmpty()) {
                    // 获取文件名
                    String filename = photo.getOriginalFilename();
                    // 将收到的文件传输到给定的目标文件。
                    photo.transferTo(new File(file.getAbsolutePath() + File.separator + System.currentTimeMillis() + filename));
                }
            }
            multiFlag = true;
        }
        if (singleFlag && multiFlag) {
            model.addAttribute("msg", "全部文件上传成功");
        }
        if (singleFlag && !multiFlag) {
            model.addAttribute("msg", "单文件上传成功");
        }
        if (!singleFlag && multiFlag) {
            model.addAttribute("msg", "多文件上传成功");
        }

        /*文件列表*/
        List<String> filesName = getFile(model);
        model.addAttribute("filesName", filesName);
        // 表单提交成功跳转到主页面
        return "upload";
    }

    /**
     * 文件下载
     */
    @ResponseBody
    @PostMapping("/download")
    public String downloadFile(Model model, HttpServletRequest request, HttpServletResponse response, String fileName){

        if (fileName != null) {
            //1、获取要下载文件的绝对路径
            //获取项目相对路径,上传文件到项目资源目录的upload下
            File directory = new File(localUploadPath);
            String realPath = null;
            FileInputStream fis = null;
            ServletOutputStream sot = null;

            try {
                realPath = directory.getCanonicalPath() + File.separator + fileName;
                System.out.println("下载的文件是：" + realPath);
                //2、获取要下载文件的文件名
                String realName = fileName;
                //3、让浏览器能够支持我们下载的文件[如果文件名是中文就需要转码]
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(realName, "UTF-8"));
                //4、获取下载文件的输入流
                fis = new FileInputStream(realPath);
                //5、创建缓冲区
                int len = 0;
                byte[] bytes = new byte[1024];
                //6、创建输出流
                sot = response.getOutputStream();
                //7、写出文件
                while ((len = fis.read(bytes)) != -1) {
                    sot.write(bytes, 0, len);
                    sot.flush();
                }
                model.addAttribute("msg", "<font color=\"red\">下载成功</font>");
                return "upload";
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (sot != null) {
                    try {
                        sot.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        model.addAttribute("msg", "<font color=\"red\">下载失败</font>");
        return "upload";
    }




    /*@PostMapping("/download")
    public String downloadFile(Model model, HttpServletRequest request, HttpServletResponse response, String fileName) throws IOException {

        if (fileName != null) {
            //获取项目相对路径,上传文件到项目资源目录的upload下
            File directory = new File(localUploadPath);
            String filePath = directory.getCanonicalPath();
            String pathFileName = filePath + File.separator + fileName;
            System.out.println("下载的文件夹是：" + filePath);

            File file = new File(pathFileName);
            if (file.exists()) {
                response.setContentType("application/force-download");// 设置强制下载不打开
                response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);// 设置文件名
                byte[] buffer = new byte[1024];
                FileInputStream fis = null;
                BufferedInputStream bis = null;
                try {
                    fis = new FileInputStream(file);

                    bis = new BufferedInputStream(fis);
                    // 创建输出对象
                    OutputStream os = response.getOutputStream();
                    int i = bis.read(buffer);
                    while (i != -1) {
                        os.write(buffer, 0, i);
                        i = bis.read(buffer);
                    }
                    model.addAttribute("msg", "<font color=\"green\">下载成功</font>");
                    return "upload";
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (bis != null) {
                        try {
                            bis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (fis != null) {
                        try {
                            fis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        model.addAttribute("msg", "<font color=\"red\">下载失败</font>");
        return "upload";
    }*/

    /**
     * 文件删除
     */
    @GetMapping("/deleteFile/{deleteFile}")
    public String deleteFile(Model model, @PathVariable String deleteFile, HttpServletRequest request) throws IOException {
        /*文件列表*/
        List<String> filesName = getFile(model);
        model.addAttribute("filesName", filesName);

        if (deleteFile != null) {
            //获取项目相对路径,上传文件到项目资源目录的upload下
            File directory = new File(localUploadPath);
            String filePath = directory.getCanonicalPath();
            String pathFileName = filePath + File.separator + deleteFile;
            System.out.println("删除的文件是：" + pathFileName);

            File file = new File(pathFileName);
            if (file.exists()) {
                file.delete();
                return "redirect:/toUpload";
            }
        }
        model.addAttribute("msg", "<font color=\"red\">删除失败</font>");
        return "upload";
    }

    /**
     * 返回上传页面
     *
     * @return 上传页面
     */
    @GetMapping("/toUploadOss")
    public String uploadToOss(Model model) throws IOException {
        return "upload-oss";
    }

    /**
     * 阿里云OSS文件上传
     * @param file 文件
     * @return 图片地址
     * @throws IOException 异常
     */
    @ResponseBody
    @PostMapping("/upImg")
    public String upImg(MultipartFile file) throws IOException {
        return UploadUtil.uploadImage(file);
    }
}
